/*
 * TestFul - http://code.google.com/p/testful/
 * Copyright (C) 2012 Matteo Miraz
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package testful.evolutionary;

import java.util.Iterator;
import java.util.List;
import java.util.Map;

import jmetal.base.Variable;
import testful.evolutionary.PSOLocalSearchBranch.TestWithScore;
import testful.model.Operation;

/**
 * TODO describe me!
 * 
 * @author Administrator
 */
public class SwapUtil {

	/**
	 * apply the swap operation on the solution
	 * 
	 * @param solution
	 * @param swapOp
	 */
	public static <V extends Variable> void applyChange(
			PSOSolution<V> solution, SwapOperation swapOp) {

		Iterator iter = swapOp.getSwapOperators().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			String key = (String) entry.getKey();
			V op = (V) entry.getValue();

			if (key.equals("ADD")) {
				solution.getDecisionVariables().variables_.add(op);
			} else {
				if (solution.getDecisionVariables().variables_.contains(op)) {
					solution.getDecisionVariables().variables_.remove(op);
				}
			}
		}
	}

	/**
	 * Calculate the different between two input solution
	 * 
	 * @param basedSolution
	 *            the benchmark solution
	 * @param solution
	 * @return
	 */
	public static <V extends Variable> SwapOperation getSwapOperation(
			PSOSolution<V> basedSolution, PSOSolution<V> solution) {

		List<V> basedList = basedSolution.getDecisionVariables().variables_;
		List<V> list = solution.getDecisionVariables().variables_;

		SwapOperation swap = new SwapOperation();

		for (V v : basedList) {
			if (!list.contains(v)) {
				swap.getSwapOperators().put(new String("ADD"), (Operation) v);
			}
		}

		for (V v : list) {
			if (!basedList.contains(v)) {
				swap.getSwapOperators()
				.put(new String("REMOVE"), (Operation) v);
			}
		}

		return swap;
	}

	public static SwapOperation getSwapOperation(TestWithScore basedSolution,
			TestWithScore solution) {
		List<Operation> basedList = basedSolution.test.getTestOps();
		List<Operation> list = solution.test.getTestOps();

		SwapOperation swap = new SwapOperation();

		for (Operation v : basedList) {
			if (!list.contains(v)) {
				swap.getSwapOperators().put(new String("ADD"), v);
			}
		}

		for (Operation v : list) {
			if (!basedList.contains(v)) {
				swap.getSwapOperators().put(new String("REMOVE"), v);
			}
		}

		return swap;
	}

	public static void applyChange(TestWithScore solution, SwapOperation swapOp) {

		Iterator iter = swapOp.getSwapOperators().entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			String key = (String) entry.getKey();
			Operation op = (Operation) entry.getValue();

			if (key.equals("ADD")) {
				solution.test.getTestOps().add(op);

				//update the operation array
				Operation[] tmp = new Operation[solution.test.getTestOps()
				                                .size()];
				int i = 0;
				for (Operation o : solution.test.getTestOps()) {
					tmp[i] = o;
					i++;
				}
				solution.test.setTest(tmp);
			} else {

				if (solution.test.getTestOps().contains(op)) {
					solution.test.getTestOps().remove(op);

					//update the operation array
					Operation[] tmp = new Operation[solution.test.getTestOps()
					                                .size()];
					int i = 0;
					for (Operation o : solution.test.getTestOps()) {
						tmp[i] = o;
						i++;
					}
					solution.test.setTest(tmp);
				}
			}
		}
	}

	/**
	 * Calculate the different between two input solution list
	 * 
	 * @param basedList
	 *            the benchmark solution list
	 * @param list
	 * @return
	 */
	public static <V extends Variable> SwapOperation getSwapOperation(
			List<V> basedList, List<V> list) {

		SwapOperation swap = new SwapOperation();

		for (V v : basedList) {
			if (!list.contains(v)) {
				swap.getSwapOperators().put(new String("ADD"), (Operation) v);
			}
		}

		for (V v : list) {
			if (!basedList.contains(v)) {
				swap.getSwapOperators()
				.put(new String("REMOVE"), (Operation) v);
			}
		}
		return swap;
	}
}
